package com.yelink.metrics.core;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.stereotype.Component;

import com.yelink.metrics.api.MetricsApi;
import com.yelink.metrics.api.dto.TriggerCallbackDTO;
import com.yelink.metrics.core.domain.BaseMetricsEntity;
import com.yelink.metrics.core.domain.TargetModel;
import com.yelink.metrics.core.service.BaseMetricsService;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

/**
 * 指标触发器
 * @author idea
 */
@Slf4j
@Component
public class TriggerHandler {

    @Resource
    private MetricsApi metricsApi;
    private final Map<String, BaseMetricsService> metricsServiceMap = new ConcurrentHashMap<>();


    @PostConstruct
    public void init(){
        Map<String, BaseMetricsService> beansOfType = SpringUtil.getBeansOfType(BaseMetricsService.class);
        metricsServiceMap.putAll(
                // 这里如果 methodName为空或重复，启动时会报错。这样是合理的
                beansOfType.values().stream().collect(Collectors.toMap(BaseMetricsService::getTargetName, Function.identity()))
        );
    }

    @SuppressWarnings("unchecked")
    public <T extends BaseMetricsEntity> void trigger(TargetModel targetModel) {
        if(targetModel == null) {
            log.warn("【触发器】指标为空, 本次放弃");
            return;
        }
        String targetName = targetModel.getTargetName();
        String errMsg = null;
        List<T> originTargetDataList = null;
        try {
            BaseMetricsService<T> baseMetricsService = (BaseMetricsService<T>) metricsServiceMap.get(targetName);
            if(baseMetricsService == null) {
                log.warn("【触发器】指标名：{} 对应的服务类未找到, 本次放弃", targetName);
                return;
            }
            log.info("【触发器】指标名：{} 开始处理数据", targetName);
            List<T> results = baseMetricsService.deal(targetModel);
            if(CollUtil.isNotEmpty(results)) {
                // 保存结果集
                baseMetricsService.saveOrUpdateBatchByUnique(results);
            }
            log.info("【触发器】指标名：{} 完成数据储存, 本次共处理{}条指标数据", targetName, results.size());
            originTargetDataList = results;
        }catch (Exception e) {
            log.error("【触发器】指标名：{} 执行时遇到错误。", targetName, e);
            errMsg = e.getMessage();
        }
        try {
            // 触发告警
            metricsApi.triggerCallback(
                    TriggerCallbackDTO.builder()
                            .targetModelId(targetModel.getId())
                            .originTargetDataList(originTargetDataList)
                            .err(errMsg)
                            .build()
            );
        }catch (Exception e) {
            log.error("【触发器】指标名：{} 回调时遇到错误。", targetName, e);
        }

    }
}
